﻿using MadMediaManager.Core.Domain.Components;
using MadMediaManager.Core.ExtensionMethods;
using MadMediaManager.Core.Properties;
using NUnit.Framework;
using SharpTestsEx;

namespace MadMediaManager.Core.Tests.Domain.Components
{
    [TestFixture]
    public class DigitalInformationUnitValueTest
    {
        //the value to use when converting. can be any double.
        private const double Value = 5.61231231231;

        [Test]
        public void ConvertTo_ByteFromByte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Byte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            converted.Value.Should().Be.EqualTo(Value);

            from.ConvertThisTo(DigitalInformationUnit.Byte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            from.Value.Should().Be.EqualTo(Value);
        }

        [Test]
        public void ConvertTo_KilobyteFromByte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Kilobyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            converted.Value.Should().Be.EqualTo(Value * 0.0009765625);

            from.ConvertThisTo(DigitalInformationUnit.Kilobyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            from.Value.Should().Be.EqualTo(Value * 0.0009765625);
        }

        [Test]
        public void ConvertTo_MegabyteFromByte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Megabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            converted.Value.Should().Be.EqualTo(Value * 0.00000095367431640625);

            from.ConvertThisTo(DigitalInformationUnit.Megabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            from.Value.Should().Be.EqualTo(Value * 0.00000095367431640625);
        }

        [Test]
        public void ConvertTo_GigabyteFromByte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Gigabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            converted.Value.Should().Be.EqualTo(Value * 0.000000000931322574615478515625);

            from.ConvertThisTo(DigitalInformationUnit.Gigabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            from.Value.Should().Be.EqualTo(Value * 0.000000000931322574615478515625);
        }

        [Test]
        public void ConvertTo_NullFromByte_ReturnsNullForValue()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, null);

            var converted = from.ConvertTo(DigitalInformationUnit.Byte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            converted.Value.Should().Not.Have.Value();

            from.ConvertThisTo(DigitalInformationUnit.Byte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            from.Value.Should().Not.Have.Value();
        }

        [Test]
        public void ConvertTo_ByteFromKilobyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Kilobyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Byte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            converted.Value.Should().Be.EqualTo(Value * 1024);

            from.ConvertThisTo(DigitalInformationUnit.Byte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            from.Value.Should().Be.EqualTo(Value * 1024);
        }

        [Test]
        public void ConvertTo_KilobyteFromKilobyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Kilobyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Kilobyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            converted.Value.Should().Be.EqualTo(Value);

            from.ConvertThisTo(DigitalInformationUnit.Kilobyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            from.Value.Should().Be.EqualTo(Value);
        }

        [Test]
        public void ConvertTo_MegabyteFromKilobyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Kilobyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Megabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            converted.Value.Should().Be.EqualTo(Value * 0.0009765625);

            from.ConvertThisTo(DigitalInformationUnit.Megabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            from.Value.Should().Be.EqualTo(Value * 0.0009765625);
        }

        [Test]
        public void ConvertTo_GigabyteFromKilobyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Kilobyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Gigabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            converted.Value.Should().Be.EqualTo(Value * 0.00000095367431640625);

            from.ConvertThisTo(DigitalInformationUnit.Gigabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            from.Value.Should().Be.EqualTo(Value * 0.00000095367431640625);
        }


        [Test]
        public void ConvertTo_NullFromKillobyte_ReturnsNullForValue()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Kilobyte, null);

            var converted = from.ConvertTo(DigitalInformationUnit.Kilobyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            converted.Value.Should().Not.Have.Value();

            from.ConvertThisTo(DigitalInformationUnit.Kilobyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            from.Value.Should().Not.Have.Value();
        }

        [Test]
        public void ConvertTo_ByteFromMegabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Megabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Byte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            converted.Value.Should().Be.EqualTo(Value * 1048576);

            from.ConvertThisTo(DigitalInformationUnit.Byte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            from.Value.Should().Be.EqualTo(Value * 1048576);
        }

        [Test]
        public void ConvertTo_KilobyteFromMegabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Megabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Kilobyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            converted.Value.Should().Be.EqualTo(Value * 1024);

            from.ConvertThisTo(DigitalInformationUnit.Kilobyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            from.Value.Should().Be.EqualTo(Value * 1024);
        }

        [Test]
        public void ConvertTo_MegabyteFromMegabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Megabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Megabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            converted.Value.Should().Be.EqualTo(Value);

            from.ConvertThisTo(DigitalInformationUnit.Megabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            from.Value.Should().Be.EqualTo(Value);
        }

        [Test]
        public void ConvertTo_GigabyteFromMegabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Megabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Gigabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            converted.Value.Should().Be.EqualTo(Value * 0.0009765625);

            from.ConvertThisTo(DigitalInformationUnit.Gigabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            from.Value.Should().Be.EqualTo(Value * 0.0009765625);
        }

        [Test]
        public void ConvertTo_NullFromMegabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Megabyte, null);

            var converted = from.ConvertTo(DigitalInformationUnit.Megabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            converted.Value.Should().Not.Have.Value();

            from.ConvertThisTo(DigitalInformationUnit.Megabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            from.Value.Should().Not.Have.Value();
        }

        [Test]
        public void ConvertTo_ByteFromGigabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Gigabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Byte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            converted.Value.Should().Be.EqualTo(Value * 1073741824);

            from.ConvertThisTo(DigitalInformationUnit.Byte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Byte);
            from.Value.Should().Be.EqualTo(Value * 1073741824);
        }

        [Test]
        public void ConvertTo_KilabyteFromGigabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Gigabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Kilobyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            converted.Value.Should().Be.EqualTo(Value * 1048576);

            from.ConvertThisTo(DigitalInformationUnit.Kilobyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Kilobyte);
            from.Value.Should().Be.EqualTo(Value * 1048576);
        }

        [Test]
        public void ConvertTo_MegabyteFromGigabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Gigabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Megabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            converted.Value.Should().Be.EqualTo(Value * 1024);

            from.ConvertThisTo(DigitalInformationUnit.Megabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Megabyte);
            from.Value.Should().Be.EqualTo(Value * 1024);
        }

        [Test]
        public void Can_Convert_Gigabyte_To_Gigabyte()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Gigabyte, Value);

            var converted = from.ConvertTo(DigitalInformationUnit.Gigabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            converted.Value.Should().Be.EqualTo(Value);

            from.ConvertThisTo(DigitalInformationUnit.Gigabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            from.Value.Should().Be.EqualTo(Value);
        }

        [Test]
        public void ConvertTo_NullFromGigabyte_Converts()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Gigabyte, null);

            var converted = from.ConvertTo(DigitalInformationUnit.Gigabyte);
            converted.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            converted.Value.Should().Not.Have.Value();

            from.ConvertThisTo(DigitalInformationUnit.Gigabyte);
            from.Unit.Should().Be.EqualTo(DigitalInformationUnit.Gigabyte);
            from.Value.Should().Not.Have.Value();
        }
        
        [Test]
        public void ToString_ByteAndValue_ReturnsFormattedString()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, Value);
            from.ToString().Should().Be.EqualTo(string.Format("{0:0.##} {1}", from.Value, from.Unit.GetDescription()));
        }

        [Test]
        public void ToString_ByteAndNull_ReturnsFormattedString()
        {
            var from = new DigitalInformationUnitValue(DigitalInformationUnit.Byte, null);
            from.ToString().Should().Be.EqualTo(CoreResources.DigitalInformation_Value_Unkown);
        }
    }
}
